from datetime import timedelta, datetime
from typing import List, Union

from dateutil import tz
from pandas import Timestamp

from bct.tools.http.trade.bct4_trade_dto import CalcDaysType


def count_days(start: datetime, end: datetime, calc_type: CalcDaysType = CalcDaysType.INCLUSIVE_EXCLUSIVE) -> int:
    """
    计算天数，并且考虑含头含尾的条件
    :param start:
    :param end:
    :param calc_type:
    :return:
    """
    dt: timedelta = end - start
    days = dt.days
    if calc_type == CalcDaysType.EXCLUSIVE_EXCLUSIVE:
        days -= 1
    elif calc_type == CalcDaysType.INCLUSIVE_INCLUSIVE:
        days += 1
    return int(days)


def parse_date_str(date_time: datetime) -> str:
    """
    时间转换
    :param date_time:
    :return:
    """
    return date_time.strftime('%Y-%m-%d')


def trans_datetime(date_str: Union[str, Timestamp, datetime]) -> datetime:
    """
    转换成日期
    :param date_str: yyyy-MM-dd
    :return:
    """
    tz_sh = tz.gettz('Asia/Shanghai')
    datetime_time = None
    if isinstance(date_str, str):
        datetime_time = datetime.strptime(date_str + '+08:00:00', '%Y-%m-%d%z')
    elif isinstance(date_str, datetime):
        return date_str
    elif isinstance(date_str, Timestamp):
        datetime_time = trans_datetime(date_str.strftime('%Y-%m-%d'))
    return datetime_time


def is_weekend(date_time: datetime) -> bool:
    """
    是否周末
    :param date_time:
    :return:
    """
    if date_time.isoweekday() == 6:
        return True
    elif date_time.isoweekday() == 7:
        return True
    else:
        return False


def is_in_holiday(date_time: datetime, holiday: List[str]) -> bool:
    """
    是否在假日列表
    :param date_time:
    :param holiday:
    :return:
    """
    for h in holiday:
        hd = trans_datetime(h)
        if hd.date() == date_time.date():
            return True
    return False


def skip_weekend(date_time: datetime) -> datetime:
    """
    跳过周末
    :param date_time:
    :return:
    """
    if date_time.isoweekday() == 6:
        return date_time + timedelta(days=2)
    elif date_time.isoweekday() == 7:
        return date_time + timedelta(days=1)
    else:
        return date_time
